package cn.edu.sjtu.se.dslab.component.data.util;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Set;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;

import cn.edu.sjtu.se.dslab.component.data.DataAttribute;
import cn.edu.sjtu.se.dslab.component.data.DataType;
import cn.edu.sjtu.se.dslab.component.data.DomainEntity;
import cn.edu.sjtu.se.dslab.component.data.Operation;
import cn.edu.sjtu.se.dslab.pojo.CodeGenerator;
import cn.edu.sjtu.se.dslab.service.IDataTypeService;
import cn.edu.sjtu.se.dslab.service.IDomainEntityService;
import cn.edu.sjtu.se.dslab.util.Const;
import cn.edu.sjtu.se.dslab.util.Util;

@Service("domainEntityGenerator")
public class DomainEntityGenerator extends CodeGenerator {

	
	@Resource(name = "dataTypeService")
	IDataTypeService dataTypeService;
	
	@Resource(name = "domainEntityService")
	private IDomainEntityService domainEntityService;
	
	private final static String FILE_ID = "fileID";

	private final static String HEADER_LIST = "headerList";
	
	private final static String HEADER = "header";

	private final static String ENTITY_NAME = "entityName";

	private final static String COUNT_LIST = "countList";

	private final static String ATTR_LIST = "attrList";

	private final static String EXTEND_LIST = "extendList";

	private final static String FUNCTION_LIST = "functionList";

	private final static String AGGRAGATIOIN_LIST = "aggragationList";

	private final static String Entity_TemplateFile = "domain_entity.vm";
	
	private final static String Entity_Impl_TemplateFile = "domain_entity_impl.vm";

	private final static String Type_TemplateFile = "data_type.vm";

	private final static String CODE = "code";

	public DomainEntityGenerator() {
		super();
	}

	public DomainEntityGenerator(String templateFile) {
		super(templateFile);
	}

	public boolean generateEntity(DomainEntity entity, String targetFile) {
		// 加载template
		template = ve.getTemplate(Entity_TemplateFile);

		String fileId = entity.getName().replace(" ", "_").toUpperCase() + "_H";
		vc.put(FILE_ID, fileId);

		Set<DomainEntity> extendEntities = entity.getExtendsSet();

		Set<DomainEntity> aggragationEntities = entity.getAggregations();

		Set<DomainEntity> dependEntities = entity.getDepends();
		// 自有属性列表
		Set<DataAttribute> attributes = entity.getAttributes();

		Set<Operation> operations = entity.getOpertions();

		// 生成头文件引用
		Set<String> headerList = new HashSet<String>();
		if (extendEntities != null) {
			for (DomainEntity entity2 : extendEntities) {
				// 默认文件名命名方式
				String temp = entity2.getName().replace(" ", "_").toLowerCase();
				headerList.add("#include \"" + temp + ".h\"");
			}
		}
		if (aggragationEntities != null) {
			for (DomainEntity entity2 : aggragationEntities) {
				// 默认文件名命名方式
				String temp = entity2.getName().replace(" ", "_").toLowerCase();
				headerList.add("#include \"" + temp + ".h\"");
			}
		}
		if (dependEntities != null) {
			for (DomainEntity entity2 : dependEntities) {
				// 默认文件名命名方式
				String temp = entity2.getName().replace(" ", "_").toLowerCase();
				headerList.add("#include \"" + temp + ".h\"");
			}
		}

		if (attributes != null) {
			for (DataAttribute dataAttribute : attributes) {
				DomainEntity returnEntity = dataAttribute.getType();
				DataType tempType = dataTypeService.getDataTypeById(returnEntity.getId());
				// 默认文件名命名方式
				if (tempType == null|| !tempType.getCategory().equals(Const.DATA_TYPE_BASIC)) {
					String temp = dataAttribute.getType().getName()
							.replace(" ", "_").toLowerCase();
					headerList.add("#include \"" + temp + ".h\"");
				}
				
			}
		}

		if (operations != null) {
			for (Operation operation : operations) {
				DomainEntity returnEntity = operation.getInterfaceMethod().getReturnType();
				DataType tempType = dataTypeService.getDataTypeById(returnEntity.getId());
				// 默认文件名命名方式
				if (tempType == null || !tempType.getCategory().equals(Const.DATA_TYPE_BASIC)) {
					String temp = operation.getInterfaceMethod().getReturnType()
							.getName().replace(" ", "_").toLowerCase();
					headerList.add("#include \"" + temp + ".h\"");
				}
				String depTypes = operation.getInterfaceMethod().getDepType();
				if (depTypes != null) {
					String type[] = depTypes.split(";");
					Set<String> tempSet = new HashSet<String>();
					for (String string : type) {
						if (string.equals("")) continue;
						tempSet.add(string);
					}
					for (String string : tempSet) {
						DomainEntity tempEntity =  domainEntityService.getDomainEntityById(Long.parseLong(string));
						DataType temp =  dataTypeService.getDataTypeById(Long.parseLong(string));
						if (temp == null || !temp.getCategory().equals(Const.DATA_TYPE_BASIC)) {
							String head = tempEntity.getName()
									.replace(" ", "_").toLowerCase();
							headerList.add("#include \"" + head + ".h\"");
						}
					}
				}
			}
		}

		vc.put(HEADER_LIST, headerList);

		// struct 命名方式 首字母大写
		String entityName = Util.upperFirstLetter(entity.getName().replace(" ",
				"_"));
		vc.put(ENTITY_NAME, entityName);

		// 继承项
		Set<String> exEntityList = new HashSet<String>();
		if (extendEntities != null) {
			for (DomainEntity entity2 : extendEntities) {
				// 默认struct 类型命名方式
				String type = Util.upperFirstLetter(entity2.getName().replace(
						" ", "_"));

				// 默认struct 变量命名方式
				String id = Util.lowerrFirstLetter(entity2.getName().replace(
						" ", ""));

				exEntityList.add(type + " " + id);
			}
		}
		vc.put(EXTEND_LIST, exEntityList);

		// 组合项
		Set<String> aggEntityList = new HashSet<String>();
		Set<String> aggEntityCountList = new HashSet<String>();
		if (aggragationEntities != null) {
			for (DomainEntity entity2 : aggragationEntities) {
				// 默认struct 类型命名方式
				String type = Util.upperFirstLetter(entity2.getName().replace(
						" ", "_"));

				// 默认struct 变量命名方式
				String id = Util.lowerrFirstLetter(entity2.getName().replace(
						" ", ""));
				// 大小设置为10
				String countString = entity2.getName().replace(" ", "_")
						.toUpperCase()
						+ "_COUNT";
				aggEntityList.add(type + " " + id + "["
						+ countString + "];");
				aggEntityCountList.add("#define " + countString + " 10");
			}
		}

		vc.put(AGGRAGATIOIN_LIST, aggEntityList);
		vc.put(COUNT_LIST, aggEntityCountList);

		// 自有函数列表-->
		Set<String> functionList = new HashSet<String>();
		if (entity.getOpertions() != null) {
			for (Operation operation : operations) {
				// 函数指针
				//String name = operation.getInterfaceMethod().getName();
				//String returnType = operation.getInterfaceMethod()
				//		.getReturnType().getName();
				//String params = operation.getInterfaceMethod().getArguments();
				// String temp =
				// operation.getInterfaceMethod().getMethodSigniture();
				String temp = operation.getInterfaceMethod().getMethodSigniture();
				if (!temp.endsWith(";")) {
					temp = temp + ";";
				}
				functionList.add(temp);
			}
		}
		vc.put(FUNCTION_LIST, functionList);

		Set<String> attrList = new HashSet<String>();
		if (entity.getAttributes() != null) {
			for (DataAttribute attribute : attributes) {
				String temp = attribute.getType().getName() + " "
						+ attribute.getName();
				if (!temp.endsWith(";")) {
					temp = temp + ";";
				}
				attrList.add(temp);
			}
		}
		vc.put(ATTR_LIST, attrList);

		FileWriter fWriter = null;
		try {
			File writeFile = getFile(targetFile);
			fWriter = new FileWriter(writeFile);
			if (template != null) {
				template.merge(vc, fWriter);
			}
		} catch (IOException ex) {
			ex.printStackTrace();
			return false;
		} finally {
			try {
				fWriter.flush();
				fWriter.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return true;
	}
	/**
	 * 仅仅用于在领域实体有操作时，产生领域实体的实现代码
	 * @param entity
	 * @param targetFile
	 * @return
	 */
	public boolean generateEntityImplFile(DomainEntity entity, String targetFile) {
		// 加载template
		template = ve.getTemplate(Entity_Impl_TemplateFile);
		String fileName = Util.getEntityFileName(entity);
		vc.put(HEADER, "#include \""+fileName+"\"");
		// struct 命名方式 首字母大写
		String entityName = Util.upperFirstLetter(entity.getName().replace(" ",
						"_"));
		Set<Operation> operations = entity.getOpertions();

		// 自有函数列表-->
		Set<Hashtable<String, String>> functionList = new HashSet<Hashtable<String, String>>();
		if (entity.getOpertions() != null) {
			for (Operation operation : operations) {
				// 函数指针
				//String name = operation.getInterfaceMethod().getName();
				//String returnType = operation.getInterfaceMethod()
				//		.getReturnType().getName();
				//String params = operation.getInterfaceMethod().getArguments();
				//String temp = returnType + " "+entityName+"::" + name + "(" + params + ")";
				String temp = operation.getInterfaceMethod().getMethodSigniture();
				if (temp.endsWith(";")) {
					temp = temp.replace(";", "");
				}
				Hashtable< String, String> table = new Hashtable<String, String>();
				table.put("name", temp);
				System.out.println(""+operation.getId());
				table.put("implementation", operation.getInterfaceMethod().getImplementation());
				functionList.add(table);
			}
		}
		vc.put(FUNCTION_LIST, functionList);

		FileWriter fWriter = null;
		try {
			File writeFile = getFile(targetFile);
			fWriter = new FileWriter(writeFile);
			if (template != null) {
				template.merge(vc, fWriter);
			}
		} catch (IOException ex) {
			ex.printStackTrace();
			return false;
		} finally {
			try {
				fWriter.flush();
				fWriter.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return true;
	}

	public boolean generateDataType(DataType type, String targetFile) {
		// 加载template
		template = ve.getTemplate(Type_TemplateFile);

		String fileId = type.getName().replace(" ", "_").toUpperCase() + "_H";
		vc.put(FILE_ID, fileId);

		Set<DomainEntity> extendEntities = type.getExtendsSet();

		Set<DomainEntity> aggragationEntities = type.getAggregations();

		Set<DomainEntity> dependEntities = type.getDepends();
		// 自有属性列表
		Set<DataAttribute> attributes = type.getAttributes();

		Set<Operation> operations = type.getOpertions();
		// 生成头文件引用
		Set<String> headerList = new HashSet<String>();
		if (extendEntities != null) {
			for (DomainEntity entity2 : extendEntities) {
				// 默认文件名命名方式
				String temp = entity2.getName().replace(" ", "_").toLowerCase();
				headerList.add("#include \"" + temp + ".h\"");
			}
		}
		if (aggragationEntities != null) {
			for (DomainEntity entity2 : aggragationEntities) {
				// 默认文件名命名方式
				String temp = entity2.getName().replace(" ", "_").toLowerCase();
				headerList.add("#include \"" + temp + ".h\"");
			}
		}
		if (dependEntities != null) {
			for (DomainEntity entity2 : dependEntities) {
				// 默认文件名命名方式
				String temp = entity2.getName().replace(" ", "_").toLowerCase();
				headerList.add("#include \"" + temp + ".h\"");
			}
		}
		if (attributes != null) {
			for (DataAttribute dataAttribute : attributes) {
				DomainEntity returnEntity = dataAttribute.getType();
				DataType tempType = dataTypeService.getDataTypeById(returnEntity.getId());
				// 默认文件名命名方式
				if (tempType ==  null|| !tempType.getCategory().equals(Const.DATA_TYPE_BASIC)) {
					String temp = dataAttribute.getType().getName()
							.replace(" ", "_").toLowerCase();
					headerList.add("#include \"" + temp + ".h\"");
				}
				
			}
		}

		if (operations != null) {
			for (Operation operation : operations) {
				DomainEntity returnEntity = operation.getInterfaceMethod().getReturnType();
				DataType tempType = dataTypeService.getDataTypeById(returnEntity.getId());
				// 默认文件名命名方式
				if (tempType == null || !tempType.getCategory().equals(Const.DATA_TYPE_BASIC)) {
					String temp = operation.getInterfaceMethod().getReturnType()
							.getName().replace(" ", "_").toLowerCase();
					headerList.add("#include \"" + temp + ".h\"");
				}
				String depTypes = operation.getInterfaceMethod().getDepType();
				String types[] = depTypes.split(";");
				Set<String> tempSet = new HashSet<String>();
				for (String string : types) {
					tempSet.add(string);
				}
				for (String string : tempSet) {
					DomainEntity tempEntity =  domainEntityService.getDomainEntityById(Long.parseLong(string));
					DataType temp =  dataTypeService.getDataTypeById(Long.parseLong(string));
					if (temp == null || !temp.getCategory().equals(Const.DATA_TYPE_BASIC)) {
						String head = tempEntity.getName()
								.replace(" ", "_").toLowerCase();
						headerList.add("#include \"" + head + ".h\"");
					}
				}
				
			}
		}
		vc.put(HEADER_LIST, headerList);
		DataTypeUtil dataTypeUtil = new DataTypeUtil();
		String code = dataTypeUtil.getDataTypeCode(type);
		vc.put(CODE, code);

		FileWriter fWriter = null;
		try {
			File writeFile = getFile(targetFile);
			fWriter = new FileWriter(writeFile);
			if (template != null) {
				template.merge(vc, fWriter);
			}
		} catch (IOException ex) {
			ex.printStackTrace();
			return false;
		} finally {
			try {
				fWriter.flush();
				fWriter.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return true;
	}

}
